package com.zzyl.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.aliyun.iot20180120.Client;
import com.aliyun.iot20180120.models.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.zzyl.base.PageResponse;
import com.zzyl.base.ResponseResult;
import com.zzyl.constant.CacheConstants;
import com.zzyl.dto.DeviceDto;
import com.zzyl.dto.DevicePageQueryDto;
import com.zzyl.entity.Device;
import com.zzyl.enums.BasicEnum;
import com.zzyl.enums.DeviceLocationTypeEnum;
import com.zzyl.enums.DevicePhysicalLocationTypeEnum;
import com.zzyl.exception.BaseException;
import com.zzyl.mapper.DeviceMapper;
import com.zzyl.properties.AliIoTConfigProperties;
import com.zzyl.service.DeviceService;
import com.zzyl.vo.DeviceVo;
import com.zzyl.vo.ProductVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;

/**
 * @Descriptioin DeviceServiceImpl
 * @Author AvA
 * @Date 2024-10-30
 */
@Service
@Slf4j
public class DeviceServiceImpl implements DeviceService {

    @Autowired
    private AliIoTConfigProperties aliIoTConfigProperties;

    @Autowired
    private Client client;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private DeviceMapper deviceMapper;

    /**
     * 从物联网平台同步产品列表
     */
    @Override
    public void synProdectList() {

        QueryProductListRequest request = new QueryProductListRequest();
        request.setCurrentPage(1);
        request.setPageSize(100);
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryProductListResponse response;

        try {
            response = client.queryProductList(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        if (!response.getBody().getSuccess()) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        List<QueryProductListResponseBody.QueryProductListResponseBodyDataListProductInfo> productInfo
                = response.getBody().getData().getList().getProductInfo();

        List<ProductVo> productVoList = BeanUtil.copyToList(productInfo, ProductVo.class);

        redisTemplate.opsForValue().set(CacheConstants.ALL_PRODUCT_KEY, JSONUtil.toJsonStr(productVoList));
    }

    /**
     * 查询所有产品列表
     *
     * @return
     */
    @Override
    public List<ProductVo> allProduct() {

        String json = redisTemplate.opsForValue().get(CacheConstants.ALL_PRODUCT_KEY);

        if (StrUtil.isNotEmpty(json)) {
            return JSONUtil.toList(json, ProductVo.class);
        }

        return null;
    }

    /**
     * 查询指定设备的物模型运行状态
     *
     * @param request
     * @return
     */
    @Override
    public QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData QueryDevicePropertyStatus(QueryDevicePropertyStatusRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryDevicePropertyStatusResponse response;
        try {
            response = client.queryDevicePropertyStatus(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_PROPERTY_STATUS_ERROR);
        }

        QueryDevicePropertyStatusResponseBody.QueryDevicePropertyStatusResponseBodyData data = response.getBody().getData();

        return data;
    }

    /**
     * 查看指定产品的已发布物模型中的功能定义详情
     *
     * @param request
     * @return
     */
    @Override
    public QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData QueryThingModelPublished(QueryThingModelPublishedRequest request) {
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        QueryThingModelPublishedResponse response;
        try {
            response = client.queryThingModelPublished(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_THING_MODEL_PUBLISHED_ERROR);
        }

        QueryThingModelPublishedResponseBody.QueryThingModelPublishedResponseBodyData data = response.getBody().getData();
        return data;
    }

    /**
     * 删除设备
     *
     * @param deviceDto
     */
    @Override
    public void DeleteDevice(DeviceDto deviceDto) {

        Device device = BeanUtil.toBean(deviceDto, Device.class);

        DeleteDeviceRequest request = new DeleteDeviceRequest();

        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        request.setDeviceName(device.getDeviceName());
        request.setProductKey(device.getProductKey());
        request.setIotId(device.getIotId());

        try {
            client.deleteDevice(request);
        } catch (Exception e) {
            throw new RuntimeException("删除失败,请联系管理员");
        }

        deviceMapper.deleteByIotId(device.getIotId());
    }

    /**
     * 更新设备
     *
     * @param deviceDto 更新设备请求模型
     */
    @Override
    public void updateDevice(DeviceDto deviceDto) {
        //检验数据库是否存在设备
        Device dbDevice = deviceMapper.selectByPrimaryKey(deviceDto.getId());
        if (com.zzyl.utils.ObjectUtil.isEmpty(dbDevice)) {
            throw new BaseException(BasicEnum.DEVICE_NOT_EXIST);
        }

        //调用物联网接口，更新云服务设备信息
        BatchUpdateDeviceNicknameRequest request = new BatchUpdateDeviceNicknameRequest();
        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo nicknameInfo = BeanUtil.toBean(deviceDto, BatchUpdateDeviceNicknameRequest.BatchUpdateDeviceNicknameRequestDeviceNicknameInfo.class);
        request.setDeviceNicknameInfo(Lists.newArrayList(nicknameInfo));
        BatchUpdateDeviceNicknameResponse response;
        try {
            response = client.batchUpdateDeviceNickname(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }
        if (com.zzyl.utils.ObjectUtil.notEqual(Boolean.TRUE, response.getBody().getSuccess())) {
            throw new BaseException(BasicEnum.IOT_BATCH_UPDATE_DEVICE_ERROR);
        }

        // 保存位置
        Device device = BeanUtil.toBean(deviceDto, Device.class);
        //如果是随身设备，物理位置设为-1
        if (device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())) {
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }

        //更新数据库中设备信息
        try {
            deviceMapper.updateByPrimaryKeySelective(device);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.RE_SELECT_PRODUCT);
        }
    }

    /**
     * 注册设备
     *
     * @param deviceDto
     */
    @Override
    public void registerDevice(DeviceDto deviceDto) {

        //检验设备名称是否重复
        Long count = deviceMapper.countByDeviceName(deviceDto.getDeviceName());
        if (count > 0) {
            throw new BaseException(BasicEnum.DEVICE_NAME_EXIST);
        }

        //iot新增设备
        RegisterDeviceRequest registerDeviceRequest = deviceDto.getRegisterDeviceRequest();
        registerDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());

        RegisterDeviceResponse registerDeviceResponse = null;

        try {
            registerDeviceResponse = client.registerDevice(registerDeviceRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }

        //接口是否调通
        if(registerDeviceResponse == null || !registerDeviceResponse.getBody().getSuccess()){
            throw new RuntimeException(registerDeviceResponse.getBody().getErrorMessage());
        }

        Device device = BeanUtil.toBean(deviceDto, Device.class);
        device.setIotId(registerDeviceResponse.getBody().getData().getIotId());

        QueryProductRequest queryProductRequest = new QueryProductRequest();
        queryProductRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        queryProductRequest.setProductKey(device.getProductKey());

        QueryProductResponse queryProductResponse = null;
        try {
            queryProductResponse = client.queryProduct(queryProductRequest);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        if(queryProductResponse.getBody().getSuccess()){
            device.setProductName(queryProductResponse.getBody().getData().getProductName());
        }

        if(device.getLocationType().equals(DeviceLocationTypeEnum.PORTABLE_DEVICE.getOrdinal())){
            device.setPhysicalLocationType(DevicePhysicalLocationTypeEnum.ELDER.getOrdinal());
        }

        device.setHaveEntranceGuard(0);

        try {
            deviceMapper.insertSelective(device);
        } catch (Exception e) {
            //删除iot中的设备数据
            DeleteDeviceRequest deleteDeviceRequest = new DeleteDeviceRequest();
            deleteDeviceRequest.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
            deleteDeviceRequest.setDeviceName(device.getDeviceName());
            deleteDeviceRequest.setProductKey(device.getProductKey());
            deleteDeviceRequest.setIotId(device.getIotId());

            try {
                client.deleteDevice(deleteDeviceRequest);
            } catch (Exception ex) {
                throw new BaseException(BasicEnum.IOT_DELETE_DEVICE_ERROR);
            }

            throw new BaseException(BasicEnum.IOT_REGISTER_DEVICE_ERROR);
        }
    }

    /**
     * 分页查询设备列表
     * @param devicePageQueryDto
     * @return
     */
    @Override
    public PageResponse<DeviceVo> pageQueryDevice(DevicePageQueryDto devicePageQueryDto) {

        PageHelper.startPage(devicePageQueryDto.getPageNum(), devicePageQueryDto.getPageSize());

        Page<DeviceVo> page = deviceMapper.pageQueryDevice(devicePageQueryDto);

        PageResponse<DeviceVo> deviceVoPageResponse = new PageResponse<>();
        deviceVoPageResponse.setTotal(page.getTotal());
        deviceVoPageResponse.setRecords(page.getResult());

        return deviceVoPageResponse;
    }

    /**
     * 查询设备详细数据
     * @param request
     * @return
     */
    @Override
    public ResponseResult<DeviceVo> queryDeviceDetail(QueryDeviceDetailRequest request) {

        request.setIotInstanceId(aliIoTConfigProperties.getIotInstanceId());
        QueryDeviceDetailResponse response;

        try {
            response = client.queryDeviceDetail(request);
        } catch (Exception e) {
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        if(!response.getBody().getSuccess()){
            throw new BaseException(BasicEnum.IOT_QUERY_DEVICE_ERROR);
        }

        DeviceVo deviceVo = deviceMapper.selectByIotId(response.getBody().getData().getIotId());
        QueryDeviceDetailResponseBody.QueryDeviceDetailResponseBodyData data = response.getBody().getData();
        BeanUtil.copyProperties(data,deviceVo, CopyOptions.create().ignoreNullValue());

        return ResponseResult.success(deviceVo);
    }
}
